<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>ES6作用域等</title>
</head>
<body>


<script>
    /**
     * foo的作用域
     let foo = 'other';
     function bar(func = x => foo) {

        let foo='inner';
        console.log(func());
    }

     bar();*/

    /**
     * x的作用域
     let x=1;
     function foo(x,y=c=>x=2) {
        x=3;
        y();
        console.log(x);
    }


     foo();
     console.log(x);*/
    /**
     * 设置参数省略就抛出一个错误
     function throwIfMissing() {
        throw new Error('Missing parameter--没传参数报错了哦');
    }


     function foo(x=throwIfMissing()) {
        console.log(x);
        return x;
    }

     foo(1);//1
     foo();//报错*/

    /**
     * arguments变量的写法
     function sortNumbers(x) {
        //console.log(arguments);
        return Array.prototype.slice.call(arguments).sort();
    }

     // rest参数的写法
     const sortNumbers1 = (...numbers) => numbers.sort();

     console.log(sortNumbers(1,'asd')) ;
     console.log(sortNumbers1(1,'asd')) ;*/

    /**
     *结构代替apply
     function f(x, y, z) {
        // ...
        console.log(x, y, z);
    }
     var args = [0, 1, 2];
     f.apply(null, args);

     function f(v, w, x, y, z,...asd) {
     //console.log(v,w,x,y,z);
     console.log(asd);
     }
     var args = [0, 1];
     f(-1, ...args, 2, ...[3],123);*/


    /**
     //箭头函数中 this的指向
     /!*function foo() {
        id=1;
        setTimeout(()=>{console.log('id:',this.id)},0)

    }
     var id=21;

     foo();//21
     foo.call({id:42});//42*!/

     function Timer() {
        this.s1=0;
        this.s2=0;
        //箭头函数
        setInterval(()=>this.s1++,1000);
        //普通函数
        setInterval(function () {
            this.s2++
        },1000);
    }

     var s1 = 11;
     var s2 = 12;
     var timer=new Timer();


     setInterval(()=> console.log('s1:',timer.s1),1000);//使用时间函数后，this并没有改变指向
     setInterval(()=> console.log('s2:',timer.s2),1000);//使用时间函数后，this指向改变为window
     setInterval(()=> console.log('w-s2:',window.s2),1000);//window的s2被改变

     */


    /**
     //回顾ES5 this和时间函数 this ,回顾prototype
     var s1 = 11;
     var s2 = 12;


     function Timer() {
        this.s1 = 1;
        this.s2 = 2;
        /!*this.says = function () {
         console.log(this.s1, this.s2);
         }
         this.says();
         setTimeout(function () {
         console.log(this.s1, this.s2);
         }, 0);*!/

        this.says1 = function () {
            console.log(this.s1);
        }
    }

     Timer.prototype.aa = 1;
     Timer.prototype.sayt1 = function () {
        console.log(123);
    }
     Timer.prototype.sayaa = function () {
        console.log(this.aa);
    }

     var t1 = new Timer();
     var t2 = new Timer();

     //实例中的变量方法-独立
     /!* Timer.s1 = 10;
     t1.says1();
     t1.s1 = 2;
     t2.says1();*!/
     //原型中的变量方法--公用

     t1.sayt1();
     t2.sayt1();
     Timer.prototype.aa = function () {
        console.log(11111111);
    }
     Timer.prototype.aa = 2;
     t1.sayaa();
     t2.sayaa();
     console.log(t1.aa);
     t1.aa = 123;
     console.log(t1.aa);
     console.log(t2.aa);

     */


    /**
     //ES6对象的扩展
     var foo = 'bar';
     var baz = {foo};

     console.log(baz);

     function f(x, y) {
        console.log({x, y});
    }

     f(1, 2);


     var o = {
        f(){
            console.log('hello!');
        }
    }
     o.f();


     var birth = '1992/10/14';

     var Person ={
        name:'张三',
        birth,
        hello(){
            console.log('我的名字是：',this.name,'我的出生时间是：',birth);
        },
        'class':function(){
            console.log('我是以class关键字命名的简洁写法函数');
            console.log('我的名字是：',this.name,'我的出生时间是：',birth);
        }
    }

     Person.hello();//我的名字是： 张三 我的出生时间是： 1992/10/14
     Person.class();*/


    /**
     //属性名表达式
     var obj = {};
     obj.foo = true;
     obj['a' + 'bc'] = 123;

     let prokey = 'foo';
     let obj = {
     [prokey]: true,
     ['a' + 'bc']: 123
     }
     console.log(obj);

     var lastword = 'last word';
     var a = {
     'first word': 'hello',
     [lastword]: 'world'
     }

     console.log(a['first word']);//hello
     console.log(a[lastword]);//world
     console.log(a['last word']);//world


     var obj={
     ['he'+'llo'](){
     console.log('hello world');
     }
     }

     obj.hello();//hello world

     // 报错
     var foo = 'bar';
     var bar = 'abc';
     var baz = { [foo] };*/


    /**
     //代替ES5__proto__的Object.set/getPrototypeOf();

     var proto = {};
     var obj = {x: 0};
     Object.setPrototypeOf(obj, proto);

     var obj1 = {};
     obj1.__proto__ = proto;

     proto.y = 1;
     proto.z = 2;

     console.log(obj);//Object {x: 0}
     console.log(obj.y);//1
     console.log(obj.z);//2
     proto.z = 22;
     console.log(obj.z);//22
     console.log(obj1.y);//1
     console.log(obj1.z);//22

     //console.log(Object.setPrototypeOf(1, {x: 1}));
     var o = Object.setPrototypeOf({}, null);

     var a = 10;
     var o1 = Object.setPrototypeOf(a, {x: 20});
     console.log(o1, a, a.x);//10 10 undefined,如果a为对象，则x：20可加入prototype

     var o2 = Object.getPrototypeOf(a);
     console.log(o2);//Number {constructor: function, toExponential: function, toFixed: function, toPrecision: function, toString: function…}
     console.log(Number.prototype);//Number {constructor: function, toExponential: function, toFixed: function, toPrecision: function, toString: function…}
     console.log(String.prototype);
     /////////////////////////////////////////////////////////////////////

     function Proto() { }
     var p1 = new Proto();
     console.log(Object.getPrototypeOf(p1) === Proto.prototype);//true
     */
    /**

     //let obj = {'asd': 'what', 'fff': 'fuck'};

     //console.log(Object.keys(obj));//["asd", "fff"]
     //console.log(Object.values(obj));//["what", "fuck"]

     let obj = Object.create({a: '1'}, {p: {value: 42}, 'pp': {value: 22}});

     obj.cc = '123asd';
     console.log(Object.values(obj));//["123asd"] ,只返回了自身定义的属性值，
     console.log(obj);//Object {cc: "123asd", p: 42, pp: 22} 注意：本身的属性cc（深粉）和原型属性p，pp（浅粉）颜色不一样

     //Object.create方法的第二个参数添加的对象属性（属性p），如果不显式声明，默认是不可遍历的，因为p的属性描述对象的enumerable默认是false，Object.values不会返回这个属性。只要把enumerable改成true，Object.values就会返回属性p的值。*/


//给对象新加属性
    const DEFAULTS = {
        logLevel: 0,
        outputFormat: 'html'
    };

    function processContent(options) {
        options = Object.assign({}, DEFAULTS, options);
        console.log(options);

    }
    processContent({a: '112'});


    function constructor(x, y) {
        Object.assign(DEFAULTS, {x, y});
    }
    constructor('aaa','bbb');
</script>

</body>
</html>